#ifndef TBS_CPP_BUFFER_H
#define TBS_CPP_BUFFER_H

#include <base/base.hpp>
#include <memory>
#include <structs/Iterable.h>

namespace tbs::buffer {
template<typename T>
class BufferIteratorFactory;

class Buffer {
public:

  constexpr static byte success = 1;
  constexpr static byte error = 0;
  constexpr static byte stopped = 2;
  constexpr static byte empty_func = 3;

  using DataArray = std::unique_ptr<byte[]>;

  /**
   * @brief 读取操作 v当前字节的数据 index 当前序号  stop_flag读取停止标记
   *
   */
  template<typename T> using readAction = std::function<void(CONST T &v, CONST size_t &index, bool &stop_flag)>;

  /**
   * @brief Construct a new Buffer object
   *
   * @param init_size 初始化容器大小
   */
  explicit Buffer(CONST size_t &init_size = 8);

  /**
   * @brief Construct a new Buffer object from other source
   *
   * @param source 需要复制的数据的指针
   * @param len 数据长度
   * @param cap 容器大小
   */
  Buffer(const void *source, const size_t &len, const size_t &cap);

  Buffer(Buffer &&other) noexcept;


  Buffer &operator=(Buffer &&other) NO_EXCEPT;

  template<typename T>
  BufferIteratorFactory<T> asIterator();

  /**
   * @brief 复制本buffer
   *
   * @return Buffer
   */
  Buffer clone() CONST;

  /**
   * @brief 根据指定类型读取数据
   *
   * @tparam T
   * @param act
   * @return 结果代号
   */

  template<typename T>
  byte read(readAction<T> act) CONST;

  /**
   * @brief 写入数据
   *
   * @param source 数据源
   * @param len 数据写入的长度
   * @param from 从buffer区中from位置开始写入
   */
  void write(const void *source, const size_t &len, const size_t &from = 0);

  void append(const void *source, const size_t &len);

  template<class T>
  void append_t(T &&source);

  /**
   * @brief 写入数据
   *
   * @param source 数据源
   * @param len 数据长度
   * @param resizeable 容量不够时是否重置容量长度
   */

  void write_f(const void *source, const size_t &len, const size_t &from, const bool &resizeable = true);

  /**
   * @brief 模板特化写入某一数据
   *
   * @tparam T
   * @param value
   */
  template<typename T>
  void write_t(const T &value);

  /**
   * @brief 重置容器
   *
   * @param size 容器新大小
   * @param clear true:清空原数据，false保留原数据，若容器新尺寸<容器原尺寸，则截断
   */
  void resize(const size_t &size, bool clear = true);

  template<typename T>
  T &seek(CONST size_t &index);

  template<class T>
  CONST T &seek(CONST size_t &i) CONST;

  /**
   * @brief 容量大小
   *
   * @return size_t
   */
  size_t cap() CONST NO_EXCEPT;

  template<typename T>
  size_t cap_t() CONST NO_EXCEPT;

  /**
   * @brief 写入的数据长度
   *
   * @return size_t
   */
  size_t len() CONST NO_EXCEPT;

  template<class T>
  size_t len_t() CONST NO_EXCEPT;

  DESTRUCTION(Buffer)

private:
  DataArray _data;
  size_t _cap = 0, _len = 0;
};

template<typename T>
class BufferIterator : public tbs::structs::Iterator<T> {
private:
  Buffer *_buffer;
  size_t _index;

public:
  BufferIterator(Buffer *buffer, size_t index);

  virtual tbs::structs::Iterator<T> &next() override;

  virtual bool has_next() CONST override;

  virtual T &value() override;

  virtual const void *source() CONST override;

  virtual const size_t index() CONST override;
};

template<typename T>
class BufferIteratorFactory : public tbs::structs::Iterable<BufferIterator<T>> {
private:
  Buffer &ref;
public:
  explicit BufferIteratorFactory(Buffer &ref);

  virtual BufferIterator<T> begin() NO_EXCEPT override;

  virtual BufferIterator<T> end() NO_EXCEPT override;
};

#include "inls/buffer/BufferIterator.cuh"

#include "inls/buffer/buffer.cuh"

}

#endif
